//package production.practice.common.database.es;
//
//
//import cn.hutool.json.JSONArray;
//import cn.hutool.json.JSONObject;
//import com.alibaba.fastjson.JSON;
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import lombok.Data;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//
//import org.apache.http.entity.ContentType;
//import org.apache.http.nio.entity.NStringEntity;
//import org.apache.http.util.EntityUtils;
//import org.elasticsearch.action.ActionListener;
//import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
//import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
//import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
//import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
//import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
//import org.elasticsearch.action.bulk.BulkItemResponse;
//import org.elasticsearch.action.bulk.BulkRequest;
//import org.elasticsearch.action.bulk.BulkResponse;
//import org.elasticsearch.action.delete.DeleteRequest;
//import org.elasticsearch.action.delete.DeleteResponse;
//import org.elasticsearch.action.index.IndexRequest;
//import org.elasticsearch.action.search.ClearScrollRequest;
//import org.elasticsearch.action.search.SearchRequest;
//import org.elasticsearch.action.search.SearchResponse;
//import org.elasticsearch.action.search.SearchScrollRequest;
//import org.elasticsearch.action.support.WriteRequest;
//import org.elasticsearch.action.update.UpdateRequest;
//import org.elasticsearch.client.*;
//import org.elasticsearch.client.ml.job.results.Bucket;
//import org.elasticsearch.cluster.metadata.MappingMetadata;
//import org.elasticsearch.common.collect.ImmutableOpenMap;
//import org.elasticsearch.common.unit.TimeValue;
//import org.elasticsearch.common.xcontent.XContentBuilder;
//import org.elasticsearch.common.xcontent.XContentFactory;
//import org.elasticsearch.index.query.*;
//import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
//import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
//import org.elasticsearch.index.reindex.BulkByScrollResponse;
//import org.elasticsearch.index.reindex.UpdateByQueryRequest;
//import org.elasticsearch.rest.RestStatus;
//import org.elasticsearch.script.ScriptType;
//import org.elasticsearch.search.Scroll;
//import org.elasticsearch.search.SearchHit;
//import org.elasticsearch.search.aggregations.AggregationBuilders;
//import org.elasticsearch.search.aggregations.Aggregations;
//import org.elasticsearch.search.aggregations.bucket.terms.Terms;
//import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
//import org.elasticsearch.search.aggregations.metrics.MaxAggregationBuilder;
//import org.elasticsearch.search.builder.SearchSourceBuilder;
//import org.elasticsearch.search.collapse.CollapseBuilder;
//import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
//import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
//import org.elasticsearch.search.sort.FieldSortBuilder;
//import org.elasticsearch.search.sort.SortBuilder;
//import org.elasticsearch.search.sort.SortBuilders;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.http.HttpEntity;
//import org.springframework.util.Assert;
//import org.springframework.util.CollectionUtils;
//import production.practice.common.exection.LoginException;
//import production.practice.common.exection.MessageException;
//import production.practice.pojo.entity.SysUser;
//import production.practice.utils.BinaryUtils;
//import sun.font.Script;
//
//import javax.annotation.Resource;
//import javax.swing.*;
//import javax.validation.constraints.Max;
//import java.io.IOException;
//import java.lang.reflect.Field;
//import java.lang.reflect.ParameterizedType;
//import java.lang.reflect.Type;
//import java.math.BigDecimal;
//import java.util.*;
//import java.util.Map.Entry;
//import production.practice.utils.SysUtil;
//
///**
// * ES操作抽象类
// *
// * @author guojun
// */
//@Slf4j
//@Data
//public abstract class AbstractESBaseDao<T, C> {
//
//    private static final Long DEFAULT_DOMAIN_ID = 1L;
//
//    @Resource
//    private RestHighLevelClient client;
//
//    @Value("${data.scope:}")
//    private String dataScope;
//
//    // es buffer limit. default:500*1024*1024(500M)
//    @Value("${bufferLimitBytes:524288000}")
//    private String bufferLimitBytes;
//
//    @Value("${init.data.action:false}")
//    private boolean canInit;
//
//    /**
//     * 获取索引信息
//     *
//     * @return
//     */
//    public abstract String getIndex();
//
//    /**
//     * 获取完整索引名称
//     *
//     * @return
//     */
//    protected final String getFullIndexName() {
//        return getDataScope() + getIndex();
//    }
//
//    /**
//     * 获取索引信息
//     *
//     * @return
//     */
//    public abstract String getType();
//
//    /**
//     * 获取索引信息
//     *
//     * @return
//     */
//    protected final String getFullTypeName() {
//        return getDataScope() + getType();
//    }
//
//    /**
//     * 获取数据作用域
//     *
//     * @return
//     */
//    private String getDataScope() {
//        return StringUtils.isNotBlank(dataScope) ? dataScope + "_" : "";
//    }
//
//
//    private Class<T> clazz;
//
//    /**
//     * 是否打印查询日志，某些子类不想展示则复写该方法返回false即可
//     *
//     * @return
//     */
//    protected boolean showQueryLog() {
//        return true;
//    }
//
//    @SuppressWarnings("unchecked")
//    public AbstractESBaseDao() {
//        Type type = this.getClass().getGenericSuperclass();
//        Type[] types = ((ParameterizedType) type).getActualTypeArguments();
//        clazz = (Class<T>) types[0];
//    }
//
//    public RestHighLevelClient getClient() {
//        return this.client;
//    }
//
//    /**
//     * <b>获取对象--文档属性id值搜索
//     *
//     * @param id 文档属性id值搜索
//     * @return
//     */
//    public T getById(Long id) {
//        JSONObject rs = new JSONObject();
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        sourceBuilder.from(0);
//        sourceBuilder.size(1);
//        SearchRequest searchRequest = this.getSearchRequest();
//        TermQueryBuilder query = QueryBuilders.termQuery("id", id);
//        sourceBuilder.query(query);
//        searchRequest.source(sourceBuilder);
//        try {
//            SearchResponse response = getClient().search(searchRequest, RequestOptions.DEFAULT);
//            SearchHit[] hits = response.getHits().getHits();
//            for (SearchHit hit : hits) {
//                String recordStr = hit.getSourceAsString();
//                rs = JSON.parseObject(recordStr);
//                return JSON.toJavaObject(rs, clazz);
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return null;
//    }
//
//    /**
//     * <b> 删除对象
//     *
//     * @param id 唯一标识ID
//     * @return 0:失败，1：成功
//     */
//    public Integer deleteById(Long id) {
//        Integer flag = 1;
//        DeleteRequest deleteRequest = this.getDeleteRequest(id.toString());
//        // 设置删除后得刷新策略为立即可见,因为es得刷新默认为异步刷新机制,每隔一段时间刷新索引
//        deleteRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
//        try {
//            DeleteResponse response = getClient().delete(deleteRequest, RequestOptions.DEFAULT);
//            if (response.status().equals(RestStatus.CREATED)) {
//                flag = 1;
//            }
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            flag = 0;
//        }
//        return flag;
//    }
//
//    /**
//     * <b> 保存或更新对象
//     *
//     * @param obj       对象
//     * @param isRefresh 是否立即刷新
//     * @return 0失败，其它表示成功
//     */
//    public Long saveOrUpdate(JSONObject obj, boolean isRefresh) {
//        return this.saveOrUpdateWithPrimaryKey(obj, isRefresh, "id");
//    }
//
//    /**
//     * <b> 保存或更新对象
//     *
//     * @param obj       对象
//     * @param isRefresh 是否立即刷新
//     * @return 0失败，其它表示成功
//     */
//    public Long saveOrUpdateWithPrimaryKey(JSONObject obj, boolean isRefresh, String primaryKey) {
//        BinaryUtils.checkNull(primaryKey, "主键");
//        Long id = 0L;
//        //填充一些用户信息得;如创建时间啥的等;
//        fillPreferencesInfo(obj);
//        //maolong:只是封装了一下罢了,
//        UpdateRequest uRequest = this.getUpdateRequest(obj.get(primaryKey).toString());
//        // 新增失败时重连次数，避免版本冲突报错
//        uRequest.retryOnConflict(3);
//        uRequest.doc(obj);
//        if (isRefresh) {
//            uRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
//        }
//        uRequest.docAsUpsert(true);
//        try {
//            getClient().update(uRequest, RequestOptions.DEFAULT);
//            id = obj.getLong("id");
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return id;
//    }
//
//    /**
//     * <b>批量保存或更新
//     *
//     * @param list 对象组
//     * @return
//     */
//    //maolong 他封装得与我有什么不同啊,加了一些冗余项,然后就是加了点验证,重试次数
//    public Integer saveOrUpdateBatch(JSONArray list, boolean isRefresh) {
//        Integer flag = 1;
//        BulkRequest bulkRequest = new BulkRequest();
//
//        //怎么不走上面的逻辑啊fillPreferencesInfo,,,
//        SysUser currentUser = null;
//        try {
//            currentUser = SysUtil.getCurrentUserInfo();
//        } catch (LoginException e) {
//            log.debug("无法获取当前登陆用户，该持久化信息可能会缺失[创建/修改]人信息和domain域信息不对的问题");
//        }
//        for (int i = 0; (!list.isEmpty() && i < list.size()); i++) {
//            JSONObject obj = list.getJSONObject(i);
//            fillPreferencesInfo(obj, currentUser);
//            UpdateRequest uRequest = this.getUpdateRequest(obj.get("id").toString());
//            uRequest.doc(obj);
//            uRequest.docAsUpsert(true);
//            bulkRequest.add(uRequest);
//        }
//        bulkRequest.timeout(TimeValue.timeValueMinutes(2));
//        if (isRefresh) {
//            bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
//        }
//        try {
//            BulkResponse bulkResponse = getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
//            //maolong:这里又不根据返回结果搞,上来定一个flag,作为结果
//            if (bulkResponse.hasFailures()) {
//                flag = 0;
//                log.error(bulkResponse.buildFailureMessage());
//            }
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            flag = 0;
//            throw new MessageException(e.getMessage());
//        }
//        return flag;
//    }
//
//    /**
//     * 同步批量保存或更新
//     *
//     * @param datas 对象组
//     * 这个与上面得有什么区别吗?唯一区别也就是参数不一样了吧
//     */
//    public boolean syncSaveOrUpdateBatch(Map<String, Object> datas) {
//        SysUser currentUser = null;
//        BulkRequest bulkRequest = new BulkRequest();
//        bulkRequest.timeout(TimeValue.timeValueMinutes(2));
//        boolean flag = true;
//        try {
//            currentUser = SysUtil.getCurrentUserInfo();
//        } catch (LoginException ignored) {
//        }
//
//        if (!datas.isEmpty()) {
//            for (Entry<String, Object> entry : datas.entrySet()) {
//                JSONObject documentObj = JSON.parseObject(JSON.toJSONString(entry.getValue()));
//                fillPreferencesInfo(documentObj, currentUser);
//
//                UpdateRequest uRequest = this.getUpdateRequest(entry.getKey());
//                uRequest.doc(documentObj);
//                uRequest.docAsUpsert(true);
//                bulkRequest.add(uRequest);
//            }
//
//            try {
//                BulkResponse bulkResponse = getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
//                if (bulkResponse.hasFailures()) {
//                    flag = false;
//                    log.error(bulkResponse.buildFailureMessage());
//                }
//            } catch (IOException e) {
//                log.error(e.getMessage(), e);
//                throw new MessageException(e.getMessage());
//            }
//        }
//
//        return flag;
//    }
//
//    /**
//     * 异步批量保存或更新
//     *
//     * @param datas 对象组
//     */
//    public void asyncSaveOrUpdateBatch(Map<String, Object> datas) {
//        SysUser currentUser = null;
//        BulkRequest bulkRequest = new BulkRequest();
//        bulkRequest.timeout(TimeValue.timeValueMinutes(2));
//
//        try {
//            currentUser = SysUtil.getCurrentUserInfo();
//        } catch (LoginException ignored) {
//        }
//
//        if (!datas.isEmpty()) {
//            for (Entry<String, Object> entry : datas.entrySet()) {
//                JSONObject documentObj = JSON.parseObject(JSON.toJSONString(entry.getValue()));
//                fillPreferencesInfo(documentObj, currentUser);
//
//                UpdateRequest uRequest = this.getUpdateRequest(entry.getKey());
//                uRequest.doc(documentObj);
//                uRequest.docAsUpsert(true);
//                bulkRequest.add(uRequest);
//            }
//
//            //maolong:异步执行结果啦new ActionListener<>()：定义成功和失败的回调逻辑。以及成功失败后的逻辑
//            getClient().bulkAsync(bulkRequest, RequestOptions.DEFAULT, new ActionListener<BulkResponse>() {
//                @Override
//                public void onResponse(BulkResponse bulkItemResponses) {
//                    boolean hasFailures = bulkItemResponses.hasFailures();
//                    if (hasFailures) {
//                        log.error(">>> bulkAsync save document has failures:{}", bulkItemResponses.buildFailureMessage());
//                    }
//                }
//
//                @Override
//                public void onFailure(Exception e) {
//                    log.error(">>> save document error", e);
//                }
//            });
//        }
//
//    }
//
//    /**
//     * 批量保存或更新并返回保存详情
//     *
//     * @param list    对象组
//     * @param isAsync 是否异步调用
//     * @return
//     */
//    public Map<String, Object> saveOrUpdateBatchMessage(JSONArray list, Boolean isAsync) {
//        return this.saveOrUpdateBatchMessageWithPrimaryKey(list, isAsync, "id");
//    }
//
//    /**
//     * 批量保存或更新并返回保存详情
//     *
//     * @param list    对象组
//     * @param isAsync 是否异步调用
//     * @return
//     */
//    //maolong:这个方法与上面相似,只是提供了返回得成功,失败数,可以异步和同步
//    public Map<String, Object> saveOrUpdateBatchMessageWithPrimaryKey(JSONArray list, Boolean isAsync, String primaryKey) {
//        Map<String, Object> retMap = new HashMap<String, Object>();
//        if (list != null && list.size() > 0) {
//            BulkRequest bulkRequest = new BulkRequest();
//            SysUser currentUser = null;
//            try {
//                currentUser = SysUtil.getCurrentUserInfo();
//            } catch (LoginException e) {
//                log.debug("无法获取当前登陆用户，该持久化信息可能会缺失[创建/修改]人信息和domain域信息不对的问题");
//            }
//            for (int i = 0; (!list.isEmpty() && i < list.size()); i++) {
//                JSONObject obj = list.getJSONObject(i);
//                fillPreferencesInfo(obj, currentUser);
//                UpdateRequest uRequest = this.getUpdateRequest(obj.get(primaryKey).toString());
//                uRequest.doc(obj);
//                uRequest.docAsUpsert(true);
//                bulkRequest.add(uRequest);
//            }
//            bulkRequest.timeout(TimeValue.timeValueMinutes(2));
//            // bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
//            if (isAsync) {
//                getClient().bulkAsync(bulkRequest, RequestOptions.DEFAULT, new ActionListener<BulkResponse>() {
//
//                    int fail = 0;
//
//                    int success = 0;
//
//                    @Override
//                    public void onResponse(BulkResponse response) {
//                        List<String> errMesList = new ArrayList<String>();
//                        for (BulkItemResponse item : response.getItems()) {
//                            if (item.isFailed()) {
//                                fail++;
//                                errMesList.add(item.getFailureMessage());
//                            } else {
//                                success++;
//                            }
//                        }
//                        if (response.hasFailures()) {
//                            log.info(response.buildFailureMessage());
//                        }
//                        retMap.put("failCount", fail);
//                        retMap.put("successCount", success);
//                        retMap.put("errMessge", errMesList);
//                    }
//
//                    @Override
//                    public void onFailure(Exception e) {
//                        log.error(e.getMessage(), e);
//                    }
//                });
//            } else {
//                int fail = 0;
//                bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
//                try {
//                    BulkResponse bulkResponse = getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
//                    List<String> errMesList = new ArrayList<String>();
//                    for (BulkItemResponse item : bulkResponse.getItems()) {
//                        if (item.isFailed()) {
//                            fail++;
//                            errMesList.add(item.getFailureMessage());
//                        }
//                    }
//                    if (bulkResponse.hasFailures()) {
//                        log.error(bulkResponse.buildFailureMessage());
//                    }
//                    retMap.put("failCount", fail);
//                    retMap.put("errMessge", errMesList);
//                } catch (Exception e) {
//                    log.error(e.getMessage(), e);
//                }
//            }
//        }
//        return retMap;
//    }
//
//    /**
//     * <b>批量删除对象
//     *
//     * @param ids
//     * @return
//     */
//    public Integer deleteByIds(Collection<Long> ids) {
//        Integer flag = 1;
//        BulkRequest bulkRequest = new BulkRequest();
//        bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
//        ids.forEach(id -> {
//            DeleteRequest delRequest = this.getDeleteRequest(id.toString());
//            bulkRequest.add(delRequest);
//        });
//        bulkRequest.timeout(TimeValue.timeValueMinutes(2));
//        try {
//            BulkResponse bulkResponse = getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
//            if (bulkResponse.hasFailures()) {
//                flag = 0;
//                log.error(bulkResponse.buildFailureMessage());
//            }
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            flag = 0;
//            throw new MessageException(e.getMessage());
//        }
//        return flag;
//    }
//
//    /**
//     * <b> 分页获取对象
//     *
//     * @param pageNum  页码
//     * @param pageSize 页大小
//     * @param query    查询条件
//     * @return
//     */
//    public Page<T> getListByQuery(int pageNum, int pageSize, QueryBuilder query) {
//        JSONArray rs = new JSONArray();
//        SearchRequest searchRequest = this.getSearchRequest();
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        int from = (pageNum - 1) * pageSize < 0 ? 0 : (pageNum - 1) * pageSize;
//        sourceBuilder.from(from);
//        sourceBuilder.size(pageSize);
//        sourceBuilder.query(query);
//        //maolong 开启对匹配文档总数的精确统计;不开启,最多1w条,开启精确统计匹配的数量,性能差点
//        sourceBuilder.trackTotalHits(true);
//        searchRequest.source(sourceBuilder);
//        long totalCount = 0L;
//        try {
//            //maolong 通过defult来获取他的构造类,通过设置这个 HeapBufferedResponseConsumerFactory，你可以：
//            //允许客户端接收更大的响应体（如 500MB）。
//            //防止因响应过大而导致的 Result window is too large 或 EntityTooLargeException 等错误。
//            //提高处理大数据量搜索结果的能力（例如导出、聚合等操作）。
//            RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
//            builder.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(Integer.valueOf(bufferLimitBytes)));
//            SearchResponse response = getClient().search(searchRequest, builder.build());
//            totalCount = response.getHits().getTotalHits().value;
//            SearchHit[] hits = response.getHits().getHits();
//            for (SearchHit hit : hits) {
//                String recordStr = hit.getSourceAsString();
//                JSONObject result = JSON.parseObject(recordStr);
//                rs.add(result);
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return resultTransPage(pageNum, pageSize, totalCount, rs);
//    }
//
//    /**
//     * <b> 不分页获取对象
//     *
//     * @param query 查询条件
//     * @return
//     */
//    public List<T> getListByQuery(QueryBuilder query) {
//        Page<T> results = getListByQuery(1, 3000, query);
//        //Assert.isTrue(results.getTotalRows() <= 3000, "不分页查询一次最多拉取3000条数据，本次查询已超出");
//        // 修改为日志提示避免直接抛出异常导致功能不可用
//        if(results.getTotalRows() > 3000){
//            log.error("不分页查询一次最多拉取3000条数据，本次查询已超出");
//        }
//        return results.getData();
//    }
//
//    public List<T> selectListByQuery(int pageNum, int pageSize, QueryBuilder query) {
//        Page<T> results = getListByQuery(pageNum, pageSize, query);
//        return results.getData();
//    }
//
//    public T selectOne(QueryBuilder query) {
//        Page<T> page = getListByQuery(1, 1, query);
//        if (!BinaryUtils.isEmpty(page) && !BinaryUtils.isEmpty(page.getData())) {
//            return page.getData().get(0);
//        }
//        return null;
//    }
//
//    /**
//     * 获取列表根据查询条件-游标实现
//     *
//     * @param query
//     * @return
//     */
//    // maolong:实现了深度分页啦
//    public List<T> getListByQueryScroll(QueryBuilder query) {
//        List<T> returnVals = new LinkedList<>();
//        Map<String, Page<T>> pageResult = this.getScrollByQuery(1, 3000, query, "id", true);
//        String scrollId = pageResult.keySet().iterator().next();
//        try {
//            if (pageResult.get(scrollId).getData() != null && pageResult.get(scrollId).getData().size() > 0) {
//                returnVals.addAll(pageResult.get(scrollId).getData());
//            }
//            if (pageResult.get(scrollId).getTotalRows() > 3000) {
//                while (true) {
//                    List<T> nextResults = this.getListByScroll(scrollId);
//                    if (nextResults != null && nextResults.size() > 0) {
//                        returnVals.addAll(nextResults);
//                    } else {
//                        break;
//                    }
//                }
//            }
//        } catch (Exception e) {
//            log.error("", e);
//        } finally {
//            this.clearScroll(scrollId);
//        }
//        return returnVals;
//    }
//
//    /**
//     * <b> 分页获取对象
//     *
//     * @param pageNum   页码
//     * @param pageSize  页大小
//     * @param query     查询条件
//     * @param sortField 必须是关键字或数字类型字段
//     * @param isAsc     是否是升序
//     * @return
//     */
//    //maolong:额外整这一步,是为了干嘛?直接一个方法不好吗
//    //是为了可以直接调用下面的方法,省了封装了,这个方法是
//    public Page<T> getSortListByQuery(int pageNum, int pageSize, QueryBuilder query, String sortField, boolean isAsc) {
//        SortOrder orderType = isAsc ? SortOrder.ASC : SortOrder.DESC;
//        if (sortField == null || sortField.trim().equals("")) {
//            sortField = "id";
//        }
//        // 不知道这里为什么要转驼峰，先注掉了
//        // sortField = ESUtil.underlineToCamel(sortField);
//        List<SortBuilder<?>> sorts = new LinkedList<>();
//        sorts.add(SortBuilders.fieldSort(sortField).order(orderType));
//        return getSortListByQuery(pageNum, pageSize, query, sorts);
//    }
//
//    /**
//     * <b>排序分页获取对象
//     *
//     * @param pageNum  页码
//     * @param pageSize 页大小
//     * @param query    查询条件
//     * @param sorts    排序对象
//     * @return
//     */
//    public Page<T> getSortListByQuery(int pageNum, int pageSize, QueryBuilder query, List<SortBuilder<?>> sorts) {
//        JSONArray rs = new JSONArray();
//        SearchRequest searchRequest = this.getSearchRequest();
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        int from = (pageNum - 1) * pageSize < 0 ? 0 : (pageNum - 1) * pageSize;
//        sourceBuilder.from(from);
//        sourceBuilder.size(pageSize);
//        sourceBuilder.query(query);
//        for (SortBuilder<?> sort : sorts) {
//            if (sort instanceof FieldSortBuilder) {
//                FieldSortBuilder sortBuilder = (FieldSortBuilder)sort;
//                // maolong 处理异常,处理mapping中的映射类型,如果字段不存在，默认当作 integer 类型处理，避免报错。
//                sortBuilder.unmappedType("integer");
//                sourceBuilder.sort(sortBuilder);
//            } else {
//                sourceBuilder.sort(sort);
//            }
//        }
//        sourceBuilder.trackTotalHits(true);
//        searchRequest.source(sourceBuilder);
//        if (showQueryLog()) {
//            log.debug(searchRequest.toString());
//        }
//        long totalCount = 0L;
//        try {
//            RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
//            builder.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(Integer.valueOf(bufferLimitBytes)));
//            SearchResponse response = getClient().search(searchRequest, builder.build());
//            totalCount = response.getHits().getTotalHits().value;
//            SearchHit[] hits = response.getHits().getHits();
//            for (SearchHit hit : hits) {
//                String recordStr = hit.getSourceAsString();
//                JSONObject result = JSON.parseObject(recordStr);
//                rs.add(result);
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return resultTransPage(pageNum, pageSize, totalCount, rs);
//    }
//
//    /**
//     * <b>排序分页获取对象
//     *
//     * @param pageNum  页码
//     * @param pageSize 页大小
//     * @param query    查询条件
//     * @param sorts    排序对象
//     * @return
//     */
//    //maolong :高亮封装
//    @SuppressWarnings({"unchecked", "rawtypes"})
//    public Page<T> getSortListByHighLightQuery(int pageNum, int pageSize, QueryBuilder query, List<SortBuilder<?>> sorts, Collection<String> highLightFields) {
//        JSONArray rs = new JSONArray();
//        SearchRequest searchRequest = this.getSearchRequest();
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        int from = (pageNum - 1) * pageSize < 0 ? 0 : (pageNum - 1) * pageSize;
//        sourceBuilder.from(from);
//        sourceBuilder.size(pageSize);
//        sourceBuilder.query(query);
//        HighlightBuilder highlightBuilder = new HighlightBuilder();
//        if (BinaryUtils.isEmpty(highLightFields)) {
//            //maolong 3000 是 fragment_size，表示返回的高亮片段的最大字符数。
//            highlightBuilder.field("attrs.*", 3000);// 高亮的字段
//        } else {
//            for (String highLightField : highLightFields) {
//                highlightBuilder.field(highLightField, 3000);// 高亮的字段
//            }
//        }
//        //maolong 是否要求字段必须匹配查询条件才高亮
//        highlightBuilder.requireFieldMatch(false);// 是否多个字段都高亮
//        highlightBuilder.preTags("<b>");// 前缀后缀
//        highlightBuilder.postTags("</b>");
//        sourceBuilder.highlighter(highlightBuilder);
//        for (SortBuilder<?> sort : sorts) {
//            if (sort instanceof FieldSortBuilder) {
//                FieldSortBuilder sortBuilder = (FieldSortBuilder)sort;
//                sortBuilder.unmappedType("integer");
//                sourceBuilder.sort(sortBuilder);
//            } else {
//                sourceBuilder.sort(sort);
//            }
//        }
//        searchRequest.source(sourceBuilder);
//
//        if (showQueryLog()) {
//            log.debug(searchRequest.toString());
//        }
//        long totalCount = 0L;
//        try {
//            RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
//            builder.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(Integer.valueOf(bufferLimitBytes)));
//            SearchResponse response = getClient().search(searchRequest, builder.build());
//            totalCount = response.getHits().getTotalHits().value;
//            SearchHit[] hits = response.getHits().getHits();
//            for (SearchHit hit : hits) {
//                // 解析高亮字段
//                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
//                Iterator<Entry<String, HighlightField>> it = highlightFields.entrySet().iterator();
//                Map<String, Object> sourceAsMap = hit.getSourceAsMap();// 原来的结果
//                Object object = sourceAsMap.get("attrs");
//                Map attrs = JSON.parseObject(JSON.toJSONString(object), Map.class);
//                while (it.hasNext()) {
//                    Entry<String, HighlightField> next = it.next();
//                    String key = next.getKey();
//                    key = key.replace("attrs.", "").replace(".keyword", "");
//                    HighlightField highlightField = next.getValue();
//                    // 将原来的字段替换为高亮字段即可
//                    Text[] fragments = highlightField.fragments();
//                    for (Text text : fragments) {
//                        attrs.put(key, text.string());
//                    }
//                }
//                sourceAsMap.put("attrs", attrs);
//                String recordStr = JSON.toJSONString(sourceAsMap);
//                JSONObject result = JSON.parseObject(recordStr);
//                rs.add(result);
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return resultTransPage(pageNum, pageSize, totalCount, rs);
//    }
//
//    /**
//     * 根据query分页查询-sortQuery其实是匹配上的给打了100分
//     *
//     * @param pageNum     当前页数start 1
//     * @param pageSize    每页条数
//     * @param searchQuery 查询条件
//     * @param sortQuery   排序匹配条件，匹配上往前
//     * @return
//     * maolong 打分啊
//     */
//    public Page<T> getSortListByQuery(int pageNum, int pageSize, QueryBuilder searchQuery, QueryBuilder sortQuery) {
//        JSONArray rs = new JSONArray();
//        SearchRequest searchRequest = this.getSearchRequest();
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        int from = (pageNum - 1) * pageSize < 0 ? 0 : (pageNum - 1) * pageSize;
//        sourceBuilder.from(from);
//        sourceBuilder.size(pageSize);
//        FunctionScoreQueryBuilder query =
//                new FunctionScoreQueryBuilder(searchQuery, new FilterFunctionBuilder[]{new FilterFunctionBuilder(sortQuery, ScoreFunctionBuilders.weightFactorFunction(100F))});
//        sourceBuilder.query(query);
//        // ES 7的TotalHits有最大10000条限制，加此参数可返回精确totalHist值，但对性能会影响
//        sourceBuilder.trackTotalHits(true);
//        searchRequest.source(sourceBuilder);
//        if (showQueryLog()) {
//            log.debug(searchRequest.toString());
//        }
//        long totalCount = 0L;
//        try {
//            RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
//            builder.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(Integer.valueOf(bufferLimitBytes)));
//            SearchResponse response = getClient().search(searchRequest, builder.build());
//            totalCount = response.getHits().getTotalHits().value;
//            SearchHit[] hits = response.getHits().getHits();
//            for (SearchHit hit : hits) {
//                String recordStr = hit.getSourceAsString();
//                JSONObject result = JSON.parseObject(recordStr);
//                rs.add(result);
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return resultTransPage(pageNum, pageSize, totalCount, rs);
//    }
//
//    /**
//     * 条件查询带排序
//     *
//     * @param pageNum
//     * @param pageSize
//     * @param searchCdt
//     * @param sortCdt
//     * @return
//     * @see #getSortListByQuery(int, int, QueryBuilder, QueryBuilder)
//     */
//    //maolong 看到这里了,没看懂
//    public Page<T> getSortListByCdt(int pageNum, int pageSize, C searchCdt, C sortCdt) {
//        QueryBuilder searchQuery = ESUtil.cdtToBuilder(searchCdt);
//        QueryBuilder sortQuery = ESUtil.cdtToBuilder(sortCdt);
//        return getSortListByQuery(pageNum, pageSize, searchQuery, sortQuery);
//    }
//
//    /**
//     * group by ${field} 求maxField max
//     *
//     * @param maxField 用于分组的字段名，例如 "category"
//     * @param query 需要取最大值的字段名，例如 "price"
//     * @return {"xxx":100,"yy":20}
//     */
//    //maolong :聚合某一字段球最大值
//    //根据指定字段进行分组（group by），并在每组中计算另一个字段的最大值（max），最终返回每个分组对应的最大值结果。
//    public Map<String, BigDecimal> groupByFieldMaxVal(String groupField, String maxField, QueryBuilder query) {
//        Map<String, BigDecimal> fieldMaxValMap = new HashMap<>();
//        RestHighLevelClient c = getClient();
//        SearchRequest searchRequest = this.getSearchRequest();
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.size(0);
//        searchRequest.source(searchSourceBuilder);
//        searchSourceBuilder.query(query);
//        //maolong :分组
//        TermsAggregationBuilder term = AggregationBuilders.terms("field").field(groupField);
//        //限制组数maolong
//        term.size(10000);
//        //maolong: 分组后再对特定字段球最大值
//        MaxAggregationBuilder maxAggBuilder = AggregationBuilders.max("maxField").field(maxField);
//        term.subAggregation(maxAggBuilder);
//        searchSourceBuilder.aggregation(term);
//        SearchResponse searchResponse;
//        try {
//            searchResponse = c.search(searchRequest, RequestOptions.DEFAULT);
//            Aggregations agg = searchResponse.getAggregations();
//            Terms levelObject = agg.get("field");
//            for (Bucket bucket : levelObject.getBuckets()) {
//                String key = bucket.getKeyAsString();
//                if (key == null || key.length() <= 0) {
//                    key = "";
//                }
//                Max maxTerm = bucket.getAggregations().get("maxField");
//                double val = maxTerm.value();
//                if (!(Double.isInfinite(val) || Double.isNaN(val))) {
//                    fieldMaxValMap.put(key, new BigDecimal(maxTerm.value()));
//                }
//            }
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return fieldMaxValMap;
//    }
//
//    /**
//     * <b>获取统计结果
//     *
//     * @param field 统计字段
//     * @param query 查询条件
//     * @return 统计聚合后的结果
//     */
//    public Map<String, Long> groupByCountField(String field, QueryBuilder query) {
//        Map<String, Long> map = new HashMap<String, Long>();
//        RestHighLevelClient c = getClient();
//        SearchRequest searchRequest = this.getSearchRequest();
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        // 添加查询条件
//        //
//        // 默认是10
//        int size = 1000;
//        searchSourceBuilder.size(0);
//        searchRequest.source(searchSourceBuilder);
//        searchSourceBuilder.query(query);
//        TermsAggregationBuilder term = AggregationBuilders.terms("field").field(field);
//        term.size(size);
//        searchSourceBuilder.aggregation(term);
//        SearchResponse searchResponse;
//        try {
//            searchResponse = c.search(searchRequest, RequestOptions.DEFAULT);
//            Aggregations agg = searchResponse.getAggregations();
//            Terms levelObject = agg.get("field");
//            for (Bucket bucket : levelObject.getBuckets()) {
//                String key = bucket.getKeyAsString();
//                if (key == null || key.length() <= 0) {
//                    key = "";
//                }
//                map.put(key, bucket.getDocCount());
//            }
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return map;
//    }
//
//    /**
//     * <b>获取Mapping配置
//     *
//     * @param analyzerName 自定义分词器名称
//     * @return
//     */
//    public XContentBuilder getMapping(String analyzerName) {
//        // "class-analyzer"
//        XContentBuilder mapping = null;
//        try {
//            Map<String, Class<?>> initProperties = getAddInitProperties();
//            mapping = XContentFactory.jsonBuilder();
//            XContentBuilder builder = mapping.startObject().startObject(getFullTypeName()).startObject("properties").field("id", Collections.singletonMap("type", "long"))
//                    .field("createTime", Collections.singletonMap("type", "long")).field("modifyTime", Collections.singletonMap("type", "long"));
//            if (initProperties != null && initProperties.size() > 0) {
//                for (Entry<String, Class<?>> entry : initProperties.entrySet()) {
//                    String fieldName = entry.getKey();
//                    Class<?> fieldType = entry.getValue();
//                    if (fieldType == Long.class) {
//                        builder.field(fieldName, Collections.singletonMap("type", "long"));
//                    } else if (fieldType == String.class) {
//                        String fieldMapStr =
//                                "{\"analyzer\":\"my-analyzer\",\"type\":\"text\",\"fields\":{\"keyword\":{\"ignore_above\":256,\"type\":\"keyword\"},\"stdkeyword\":{\"normalizer\":\"my_normalizer\",\"ignore_above\":256,\"type\":\"keyword\"}}}";
//                        JSONObject fieldMap = JSON.parseObject(fieldMapStr);
//                        builder.field(fieldName, fieldMap.getInnerMap());
//                    }
//                }
//            }
//            builder.endObject().field("date_detection", false).startArray("dynamic_templates")
//                    // ----
//                    .startObject().startObject("string_code_stdkeyword").field("match_mapping_type", "string").field("match_pattern", "regex")
//                    .field("match", ".*?name|.*?code|.*?key|.*?Name|.*?Code|.*?Key").startObject("mapping").field("analyzer", analyzerName).field("type", "text").startObject("fields") // 子字段1
//                    .startObject("keyword").field("ignore_above", "256").field("type", "keyword").endObject() // 子字段1
//                    .startObject("stdkeyword").field("ignore_above", "256").field("type", "keyword").field("normalizer", "my_normalizer").endObject().endObject().endObject().endObject().endObject()
//                    // ----
//                    .startObject().startObject("strings").field("match_mapping_type", "string").startObject("mapping").field("analyzer", analyzerName).field("type", "text").startObject("fields")
//                    .startObject("keyword").field("ignore_above", "256").field("type", "keyword")/*
//             * .field("normalizer", "my_normalizer")
//             */.endObject().endObject().endObject().endObject().endObject().endArray().endObject().endObject();
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return mapping;
//    }
//
//    /**
//     * 额外初始属性索引
//     * 默认按照class进行初始化，根据需要重写设置初始化字段
//     *
//     * @return fieldName:type[Long/String]
//     */
//    protected Map<String, Class<?>> addInitProperties() {
//        Map<String, Class<?>> classMap = new HashMap<String, Class<?>>(32);
//        Class<T> tempClazz = clazz;
//        //JSONObject对象不进行初始化字段
//        if (tempClazz.getName().contains("JSONObject")) {
//            return null;
//        }
//        while (true) {
//            Field[] fields = tempClazz.getDeclaredFields();
//            if (!BinaryUtils.isEmpty(fields)) {
//                for (Field field : fields) {
//                    //排除基础字段，防止重复创建问题
//                    if (field.getName().equals("id") || field.getName().equals("createTime") || field.getName().equals("modifyTime")) {
//                        continue;
//                    }
//                    //添加初始索引仅支持Long/String
//                    if (field.getType().getName().equals("java.lang.String") || field.getType().getName().equals("java.lang.Long")) {
//                        if (classMap.containsKey(field.getName())) {
//                            continue;
//                        }
//                        classMap.put(field.getName(), field.getType());
//                    }
//                }
//            }
//            //初始化继承父类的属性字段
//            if (tempClazz.getSuperclass().getName().equals("java.lang.Object")) {
//                break;
//            } else {
//                tempClazz = (Class<T>) tempClazz.getSuperclass();
//            }
//        }
//        return classMap;
//    }
//
//    private Map<String, Class<?>> getAddInitProperties() {
//        Map<String, Class<?>> res = addInitProperties();
//        if (res != null) {
//            res.values().forEach(val -> Assert.isTrue(val == Long.class || val == String.class, "添加初始索引仅支持Long/String"));
//        }
//        return res;
//    }
//
//    /**
//     * <b>获取Setting配置
//     *
//     * @param analyzerName
//     * @return
//     */
//    public XContentBuilder getSetting(String analyzerName) {
//        //默认一个Shards
//        XContentBuilder setting = getSetting(analyzerName, 1);
//        return setting;
//    }
//
//    /**
//     * <b>获取Setting配置
//     *
//     * @param analyzerName
//     * @return
//     */
//    public XContentBuilder getSetting(String analyzerName, int number_of_shards) {
//        XContentBuilder setting = null;
//        try {
//            setting = XContentFactory.jsonBuilder();
//            setting.startObject().startObject("analysis").startObject("normalizer").startObject("my_normalizer").field("type", "custom").field("char_filter", new ArrayList<>())
//                    .field("filter", Arrays.asList("lowercase")).endObject().endObject().startObject("analyzer").startObject(analyzerName).array("filter", "lowercase", "reverse")
//                    .field("tokenizer", "ngram").field("min_gram", "1").field("max_gram", "1").endObject().endObject().endObject()
//                    .field("number_of_shards", number_of_shards).endObject();
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return setting;
//    }
//
//    /**
//     * <b>按条件删除
//     *
//     * @param query     查询条件
//     * @param isRefresh 是否立即刷新
//     * @return
//     */
//    //maolong:上面的都没看,setting和mapping
//    //这里的怎么跟我学的有点不太一样的感觉,为啥不用DelRequest,因为不支持条件查询
//    public Integer deleteByQuery(QueryBuilder query, boolean isRefresh) {
//        RestClient lowClient = getClient().getLowLevelClient();
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        sourceBuilder.query(query);
//        HttpEntity entity = new NStringEntity(sourceBuilder.toString(), ContentType.APPLICATION_JSON);
//        try {
//            String url = "/" + getFullIndexName() + "/_delete_by_query?conflicts=proceed&refresh=" + isRefresh;
//            Request request = new Request("POST", url);
//            request.setEntity(entity);
//            Response res = lowClient.performRequest(request);
//            if (res.getStatusLine().getStatusCode() != 200) {
//                return 0;
//            }
//            return 1;
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//    }
//
//    /**
//     * <b>查询更新
//     *
//     * @param query     查询条件
//     * @param scriptStr 查询的脚本,格式：ctx._source.文档字段=值 simple: 多个属性更新：
//     *                  "ctx._source.attrs['应用负责人ID']='cgjabc';ctx._source.attrs['b']+=1" 子文档： ctx._source.attrs['应用负责人ID']='abc'
//     *                  文档： ctx._source.name='abc'
//     * @param isRefresh 是否立即刷新
//     * @return
//     */
//    //maolong: 没学过
//    public boolean updateByQuery(QueryBuilder query, String scriptStr, boolean isRefresh) {
//        return updateByQuery(query, scriptStr, null, isRefresh);
//    }
//
//
//
//    public boolean updateByQuery(QueryBuilder query, final String scriptStr, boolean isRefresh, Map<String, Object> params) {
//        RestHighLevelClient client = getClient();
//        //参数为索引名，可以不指定，可以一个，可以多个
//        UpdateByQueryRequest request = this.getUpdateByQueryRequest();
//        // 更新时版本冲突
//        request.setConflicts("proceed");
//        // 设置查询条件，第一个参数是字段名，第二个参数是字段的值
//        request.setQuery(query);
//        request.setRefresh(isRefresh);
//        // 更新最大文档数
////        request.setSize(10);
//        // 批次大小
//        request.setBatchSize(3000);
////		request.setPipeline("my_pipeline");
//        Script script = new Script(ScriptType.INLINE, "painless", scriptStr, params);
//        //maolong: 这个就是怎么`更新啊
//        request.setScript(script);
//        // 并行
//        request.setSlices(2);
//        // 使用滚动参数来控制“搜索上下文”存活的时间
//        request.setScroll(TimeValue.timeValueMinutes(10));
//        // 如果提供路由，则将路由复制到滚动查询，将流程限制为匹配该路由值的切分
////		request.setRouting("=cat");
//
//        // 可选参数
//        // 超时
//        request.setTimeout(TimeValue.timeValueMinutes(2));
//        // 刷新索引
//        //request.setRefresh(true);
//        try {
//            BulkByScrollResponse response = client.updateByQuery(request, RequestOptions.DEFAULT);
//            return response.getStatus().getUpdated() > 0L;
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//    }
//
//    //maolong :到时候照着葫芦画瓢吧
//    public boolean updateByQuery(QueryBuilder query, String scriptStr, Map<String, Object> paramsMap, Boolean isRefresh) {
//        boolean flag = true;
//        RestClient lowClient = getClient().getLowLevelClient();
//        Map<String, Object> scriptMap = new HashMap<>();
//        scriptMap.put("source", scriptStr);
//        scriptMap.put("lang", "painless");
//        if (!CollectionUtils.isEmpty(paramsMap)) {
//            scriptMap.put("params", paramsMap);
//        }
//        String param = "{\"query\":" + query.toString() + ",\"script\":" + JSON.toJSONString(scriptMap) + "}";
//        HttpEntity entity = new NStringEntity(param, ContentType.APPLICATION_JSON);
//        try {
//            log.info(EntityUtils.toString(entity));
//            String url = "/" + getFullIndexName() + "/_update_by_query?conflicts=proceed&refresh=" + isRefresh.toString();
//            Request request = new Request("POST", url);
//            request.setEntity(entity);
//            Response res = lowClient.performRequest(request);
//            if (res.getStatusLine().getStatusCode() != 200) {
//                flag = false;
//            }
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            flag = false;
//            throw new MessageException(e.getMessage());
//        }
//        return flag;
//    }
//
//
//    /**
//     * <b>结果转换
//     *
//     * @param pageNum
//     * @param pageSize
//     * @param totalCount
//     * @param arr
//     * @return
//     */
//    private Page<T> resultTransPage(long pageNum, long pageSize, long totalCount, JSONArray arr) {
//        Page<T> page = new Page<T>();
//        page.setPageNum(pageNum);
//        page.setPageSize(pageSize);
//        if (totalCount == 0) {
//            page.setTotalRows(totalCount);
//            page.setTotalPages(1);
//            page.setData(arr.toJavaList(clazz));
//            return page;
//        }
//        long totalPages = totalCount % pageSize;
//        if (totalPages == 0) {
//            page.setTotalPages(totalCount / pageSize);
//        } else {
//            page.setTotalPages(totalCount / pageSize + 1);
//        }
//        page.setTotalRows(totalCount);
//        page.setData(arr.toJavaList(clazz));
//        return page;
//    }
//
//
//    public void initIndex() {
//        //默认一个shards
//        initIndex(1);
//    }
//
//    /**
//     * <b>初始化索引,
//     */
//    //maolong: 创建索引库相当于
//    public void initIndex(int number_of_shards) {
//        try {
//            RestHighLevelClient clientc = getClient();
//            GetIndexRequest getRequest = new GetIndexRequest();
//            getRequest.indices(getFullIndexName());
//            boolean existIndex = clientc.indices().exists(getRequest, RequestOptions.DEFAULT);
//            if (!existIndex) {
//                CreateIndexRequest createIndex = new CreateIndexRequest(getFullIndexName());
//                createIndex.settings(getSetting("my-analyzer", number_of_shards));
//                createIndex.mapping(getFullTypeName(), getMapping("my-analyzer"));
//                clientc.indices().create(createIndex, RequestOptions.DEFAULT);
//                HashMap<String, Object> map = new HashMap<String, Object>();
//                map.put("index.mapping.total_fields.limit", 20000);
//                map.put("index.max_result_window", 100000000);
//                UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest();
//                updateSettingsRequest.settings(map);
//                clientc.indices().putSettings(updateSettingsRequest, RequestOptions.DEFAULT);
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//        }
//    }
//
//    public void initIndex(List<T> list) {
//        if(canInit){
//            //默认一个shards
//            initIndex(list, 1);
//        }
//    }
//
//    public void initIndex(List<T> list,boolean canInit) {
//        this.canInit = canInit;
//        initIndex(list);
//    }
//
//    /**
//     * <b>初始化索引并且初始化数据
//     */
//    //感觉有点多余,整的业务代码看不懂是啥
//    public void initIndex(List<T> list, int number_of_shards) {
//        try {
//            RestHighLevelClient clientc = getClient();
//            GetIndexRequest getRequest = new GetIndexRequest();
//            getRequest.indices(getFullIndexName());
//            boolean existIndex = clientc.indices().exists(getRequest, RequestOptions.DEFAULT);
//            if (!existIndex) {
//                CreateIndexRequest createIndex = new CreateIndexRequest(getFullIndexName());
//                createIndex.settings(getSetting("my-analyzer", number_of_shards));
//                createIndex.mapping(getFullTypeName(), getMapping("my-analyzer"));
//                clientc.indices().create(createIndex, RequestOptions.DEFAULT);
//                HashMap<String, Object> map = new HashMap<String, Object>();
//                map.put("index.mapping.total_fields.limit", 2000);
//                map.put("index.max_result_window", 100000000);
//                UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(getFullIndexName());
//                updateSettingsRequest.settings(map);
//                clientc.indices().putSettings(updateSettingsRequest, RequestOptions.DEFAULT);
//                saveOrUpdateBatch(list);
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//        }
//    }
//
//    /**
//     * <b> 根据查询对象查询（代码生成器生成的查询对象）
//     *
//     * @param pageNum
//     * @param pageSize
//     * @param obj
//     * @return
//     */
//    public Page<T> getListByCdt(int pageNum, int pageSize, C obj) {
//        QueryBuilder query = ESUtil.cdtToBuilder(obj);
//        return getListByQuery(pageNum, pageSize, query);
//    }
//
//    /**
//     * <b> 根据查询对象排序查询（代码生成器生成的查询对象）
//     *
//     * @param pageNum
//     * @param pageSize
//     * @param obj
//     * @return
//     */
//    public Page<T> getSortListByCdt(int pageNum, int pageSize, C obj, List<SortBuilder<?>> sorts) {
//        QueryBuilder query = ESUtil.cdtToBuilder(obj);
//        return getSortListByQuery(pageNum, pageSize, query, sorts);
//    }
//
//    /**
//     * <b> 根据查询对象排序查询（代码生成器生成的查询对象）
//     *
//     * @param pageNum   当前页数，从1开始
//     * @param pageSize  每页条数
//     * @param obj       cdt条件
//     * @param sortField 排序字段，传空或空字符串则默认为id
//     * @param isAsc     是否升序排序
//     * @return
//     */
//    public Page<T> getSortListByCdt(int pageNum, int pageSize, C obj, String sortField, boolean isAsc) {
//        SortOrder orderType = isAsc ? SortOrder.ASC : SortOrder.DESC;
//        if (sortField == null || sortField.trim().equals("")) {
//            sortField = "id";
//        }
//        List<SortBuilder<?>> sorts = new LinkedList<>();
//        sorts.add(SortBuilders.fieldSort(sortField).order(orderType));
//        return getSortListByCdt(pageNum, pageSize, obj, sorts);
//    }
//
//    /**
//     * 根据查询对象查询（不分页）
//     *
//     * @param obj
//     * @return
//     */
//    public List<T> getListByCdt(C obj) {
//        Page<T> results = getListByCdt(1, 3000, obj);
//        // 修改为日志提示避免直接抛出异常导致功能不可用
//        if(results.getTotalRows() > 3000){
//            log.error("不分页查询一次最多拉取3000条数据，本次查询已超出");
//        }
//        return results.getData();
//    }
//
//    /**
//     * 根据查询对象排序查询（不分页）
//     *
//     * @param obj
//     * @return
//     */
//    public List<T> getSortListByCdt(C obj, List<SortBuilder<?>> sorts) {
//        Page<T> results = getSortListByCdt(1, 3000, obj, sorts);
//        // 修改为日志提示避免直接抛出异常导致功能不可用
//        if(results.getTotalRows() > 3000){
//            log.error("不分页查询一次最多拉取3000条数据，本次查询已超出");
//        }
//        return results.getData();
//    }
//
//    /**
//     * 保存数据的前置操作
//     *
//     * @param t
//     */
//    protected void savePreOption(T t) {
//        if (t != null) {
//            savePreOptionCore(t);
//        }
//    }
//
//    /**
//     * 保存数据的前置操作-需要的索引自行覆盖
//     *
//     * @param t
//     */
//    protected void savePreOptionCore(T t) {
//    }
//
//    /**
//     * <b>保存对象
//     *
//     * @param t
//     * @return
//     */
//    public Long saveOrUpdate(T t) {
//        savePreOption(t);
//        JSONObject json = JSON.parseObject(JSON.toJSONString(t));
//        return saveOrUpdate(json, true);
//    }
//
//    /**
//     * 保存对象，不立即刷新
//     *
//     * @param t
//     * @return
//     */
//    public Long saveOrUpdateDelayRefresh(T t) {
//        savePreOption(t);
//        JSONObject json = JSON.parseObject(JSON.toJSONString(t));
//        return saveOrUpdate(json, false);
//    }
//
//    /**
//     * <b>批量保存
//     *
//     * @param list
//     * @return
//     */
//    public Integer saveOrUpdateBatch(List<T> list) {
//        // JSONArray arr = new JSONArray();
//        // arr.addAll(list);
//        if (BinaryUtils.isEmpty(list)) {
//            return 1;
//        }
//        list.forEach(obj -> savePreOption(obj));
//        JSONArray arr = JSON.parseArray(JSON.toJSONString(list));
//        return saveOrUpdateBatch(arr, true);
//    }
//
//    /**
//     * <b>批量保存不立刻刷新
//     *
//     * @param list
//     * @return
//     */
//    public Integer saveOrUpdateBatchNoRefresh(List<T> list) {
//        // JSONArray arr = new JSONArray();
//        // arr.addAll(list);
//        if (BinaryUtils.isEmpty(list)) {
//            return 1;
//        }
//        list.forEach(obj -> savePreOption(obj));
//        JSONArray arr = JSON.parseArray(JSON.toJSONString(list));
//        return saveOrUpdateBatch(arr, false);
//    }
//
//    /**
//     * <b>清除游标、释放ES内存
//     *
//     * @param scrollId 游标ID
//     * @return
//     */
//    public Integer clearScroll(String scrollId) {
//        Integer flag = 1;
//        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
//        clearScrollRequest.addScrollId(scrollId);
//        try {
//            getClient().clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
//        } catch (IOException e) {
//            flag = 0;
//        }
//        return flag;
//    }
//
//    /**
//     * <b>获取游标
//     *
//     * @param pageNum   页码
//     * @param pageSize  页大小
//     * @param query     查询条件
//     * @param sortField 排放字段
//     * @param isAsc     是否升序
//     * @return
//     */
//    public Map<String, Page<T>> getScrollByQuery(int pageNum, int pageSize, QueryBuilder query, String sortField, boolean isAsc) {
//        JSONArray rs = new JSONArray();
//        String scrollId = null;
//        int from = (pageNum - 1) * pageSize < 0 ? 0 : (pageNum - 1) * pageSize;
//        Scroll scroll = new Scroll(TimeValue.timeValueMinutes(3L));
//        SearchRequest searchRequest = new SearchRequest(getFullIndexName());
//        searchRequest.scroll(scroll);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        if (isAsc) {
//            searchSourceBuilder.sort(SortBuilders.fieldSort(sortField));
//        } else {
//            searchSourceBuilder.sort(SortBuilders.fieldSort(sortField).order(SortOrder.DESC));
//        }
//        searchSourceBuilder.query(query);
//        searchSourceBuilder.from(from);
//        searchSourceBuilder.size(pageSize);
//        // ES 7的TotalHits有最大10000条限制，加此参数可返回精确totalHist值，但对性能会影响
//        searchSourceBuilder.trackTotalHits(true);
//        searchRequest.source(searchSourceBuilder);
//        SearchResponse searchResponse = null;
//        long totalCount = 0L;
//        try {
//            searchResponse = getClient().search(searchRequest, RequestOptions.DEFAULT);
//            SearchHit[] searchHits = searchResponse.getHits().getHits();
//            totalCount = searchResponse.getHits().getTotalHits().value;
//            for (SearchHit hit : searchHits) {
//                String res = hit.getSourceAsString();
//                JSONObject result = JSON.parseObject(res);
//                rs.add(result);
//            }
//            scrollId = searchResponse.getScrollId();
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//            return null;
//        }
//        Map<String, Page<T>> map = new HashMap<String, Page<T>>();
//        Page<T> page = resultTransPage(pageNum, pageSize, totalCount, rs);
//        map.put(scrollId, page);
//        return map;
//    }
//
//    /**
//     * 判断符合条件数据是否存在
//     *
//     * @param query
//     * @return true:存在 false:不存在
//     */
//    public boolean existByCondition(QueryBuilder query) {
//        Assert.notNull(query, "查询条件不可为空");
//        boolean dataExist = false;
//        Page<T> validResult = this.getListByQuery(1, 1, query);
//        if (validResult != null && validResult.getTotalRows() > 0) {
//            dataExist = true;
//        }
//        return dataExist;
//    }
//
//    /**
//     * 统计符合条件的数据条数
//     *
//     * @param query
//     * @return
//     */
//    public long countByCondition(QueryBuilder query) {
//        Assert.notNull(query, "查询条件不可为空");
//        Page<T> result = this.getListByQuery(1, 1, query);
//        return result.getTotalRows();
//    }
//
//    /**
//     * <b>根据游标获取数据（与getScrollByQuery、clearScroll配合使用）
//     *
//     * @param scrollId 游标ID
//     * @return
//     */
//    public List<T> getListByScroll(String scrollId) {
//        Scroll scroll = new Scroll(TimeValue.timeValueMinutes(3L));
//        SearchResponse searchResponse = null;
//        JSONArray rs = new JSONArray();
//        try {
//            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
//            scrollRequest.scroll(scroll);
//            searchResponse = getClient().scroll(scrollRequest, RequestOptions.DEFAULT);
//            SearchHit[] searchHits = searchResponse.getHits().getHits();
//            for (SearchHit hit : searchHits) {
//                String res = hit.getSourceAsString();
//                JSONObject result = JSON.parseObject(res);
//                rs.add(result);
//            }
//        } catch (IOException e) {
//            log.error(e.getMessage(), e);
//        }
//        return rs.toJavaList(clazz);
//    }
//
//    /**
//     * @param obj
//     * @see #fillPreferencesInfo(JSONObject, SysUser)
//     */
//    protected void fillPreferencesInfo(JSONObject obj) {
//        SysUser currentUser = null;
//        try {
//            currentUser = SysUtil.getCurrentUserInfo();
//        } catch (LoginException e) {
//            log.debug("无法获取当前登陆用户，该持久化信息可能会缺失[创建/修改]人信息和domain域信息不对的问题");
//        }
//        fillPreferencesInfo(obj, currentUser);
//    }
//
//    /**
//     * 填补持久化信息，如创建/修改人/domainId/id/创建/修改时间
//     *
//     * @param obj
//     */
//    protected void fillPreferencesInfo(JSONObject obj, SysUser currentUser) {
//        if (obj == null) {
//            return;
//        }
//        String userLoginCode = currentUser == null ? "system" : currentUser.getLoginCode();
//        Long nowTime = ESUtil.getNumberDateTime();
//        if (!obj.containsKey("id") || BinaryUtils.isEmpty(obj.get("id"))) {
//            // add-data处理
//            obj.put("id", ESUtil.getUUID());
//            obj.put("createTime", nowTime);
//            if (!obj.containsKey("creator") || BinaryUtils.isEmpty(obj.get("creator"))) {
//                obj.put("creator", userLoginCode);
//            }
//        } else {
//            // update-data处理
//            if (!obj.containsKey("createTime") || BinaryUtils.isEmpty(obj.get("createTime"))) {
//                obj.put("createTime", nowTime);
//            }
//        }
//        obj.put("modifyTime", nowTime);
//        obj.put("modifier", userLoginCode);
//        if (!obj.containsKey("domainId") || BinaryUtils.isEmpty(obj.get("domainId"))) {
//            obj.put("domainId", currentUser != null ? currentUser.getDomainId() : DEFAULT_DOMAIN_ID);
//        }
//    }
//
//    /**
//     * 获取list并排重
//     *
//     * @param size        获取条数
//     * @param query       查询条件
//     * @param groupColumn 去重字段
//     * @param sortCloumn  排序字段(影响去重返回那一条的结果)
//     * @param asc         是否升序(影响去重返回那一条的结果)
//     * @return 返回去重后(保留按照指定字段排序折叠第一条)的数据
//     */
//    public List<T> getListNoRepeat(int size, QueryBuilder query, String groupColumn, String sortCloumn, boolean asc) {
//        JSONArray rs = new JSONArray();
//        SearchRequest searchRequest = this.getSearchRequest();
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        int from = 0;
//        sourceBuilder.from(from);
//        sourceBuilder.size(size);
//        sourceBuilder.query(query);
//        searchRequest.source(sourceBuilder);
//        sourceBuilder.sort(sortCloumn, asc ? SortOrder.ASC : SortOrder.DESC);
//        CollapseBuilder collapse = new CollapseBuilder(groupColumn);
//        InnerHitBuilder innerHit = new InnerHitBuilder("innerData").setSize(1).addSort(SortBuilders.fieldSort(groupColumn).order(asc ? SortOrder.ASC : SortOrder.DESC));
//        collapse.setInnerHits(innerHit);
//        sourceBuilder.collapse(collapse);
//        try {
//            SearchResponse response = getClient().search(searchRequest, RequestOptions.DEFAULT);
//            SearchHit[] hits = response.getHits().getHits();
//            for (SearchHit hit : hits) {
//                String recordStr = hit.getSourceAsString();
//                JSONObject result = JSON.parseObject(recordStr);
//                rs.add(result);
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return rs.toJavaList(clazz);
//    }
//
//    protected Map<String, Object> getIndexMapping() {
//        try {
//            RestHighLevelClient clientc = getClient();
//            GetIndexRequest getRequest = new GetIndexRequest();
//            getRequest.indices(getFullIndexName());
//            GetMappingsRequest mappingRequest = new GetMappingsRequest().indices(getFullIndexName());
//            GetMappingsResponse mappingResponse = clientc.indices().getMapping(mappingRequest, RequestOptions.DEFAULT);
//            ImmutableOpenMap<String, MappingMetadata> indexMapping = mappingResponse.mappings().get(getFullIndexName());
//            return indexMapping.containsKey(getFullIndexName()) ?
//                    indexMapping.get(getFullIndexName()).getSourceAsMap() : indexMapping.get("_doc").getSourceAsMap();
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//        }
//        return null;
//    }
//
//
//
//    protected SearchResponse getSearchResponseByQuery(QueryBuilder query) {
//        RestHighLevelClient client = getClient();
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        SearchRequest searchRequest = this.getSearchRequest();
//        sourceBuilder.query(query);
//        searchRequest.source(sourceBuilder);
//        SearchResponse response;
//        try {
//            response = client.search(searchRequest, RequestOptions.DEFAULT);
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            throw new MessageException(e.getMessage());
//        }
//        return response;
//    }
//
//    protected DeleteRequest getDeleteRequest(String id) {
//        return new DeleteRequest(getFullIndexName(), id);
//    }
//
//    protected IndexRequest getIndexRequest(String id) {
//        return new IndexRequest(getFullIndexName(), null, id);
//    }
//
//    protected UpdateRequest getUpdateRequest(String id) {
//        return new UpdateRequest(getFullIndexName(), id);
//    }
//
//    private SearchRequest getSearchRequest() {
//        return new SearchRequest(getFullIndexName());
//    }
//
//    private UpdateByQueryRequest getUpdateByQueryRequest() {
//        return new UpdateByQueryRequest(getFullIndexName());
//    }
//}
